﻿#region File and License Information
/*
<File>
	<Copyright>Copyright © 2009, Daniel Vaughan. All rights reserved.</Copyright>
	<License>
	This file is part of DanielVaughan's Core Library

    DanielVaughan's Core Library is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    DanielVaughan's Core Library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with DanielVaughan's Core Library.  If not, see http://www.gnu.org/licenses/.
	</License>
	<Owner Name="Daniel Vaughan" Email="dbvaughan@gmail.com"/>
	<CreationDate>2010-08-15 12:24:24Z</CreationDate>
</File>
*/
#endregion

using System;
using System.Collections.Generic;

using DanielVaughan.ServiceLocation;

using Microsoft.Practices.ServiceLocation;

namespace DanielVaughan
{
	/// <summary>
	/// This class is used to retrieve object instances, using type associations,
	/// and to create associations between types and object instances.
	/// This class is set to replace the ServiceLocatorSingleton.
	/// </summary>
	public static class Locator
	{
		/// <summary>
		/// Gets the service with the specified type.
		/// </summary>
		/// <param name="serviceType">Type of the service to retrieve.</param>
		/// <returns>The service instance.</returns>
		public static object GetService(Type serviceType)
		{
			return ServiceLocator.Current.GetService(serviceType);
		}

		public static object GetInstance(Type serviceType)
		{
			return ServiceLocator.Current.GetInstance(serviceType);
		}

		public static object GetInstance(Type serviceType, string key)
		{
			return ServiceLocator.Current.GetInstance(serviceType, key);
		}

		public static IEnumerable<object> GetAllInstances(Type serviceType)
		{
			return ServiceLocator.Current.GetAllInstances(serviceType);
		}

		public static TService GetInstance<TService>()
		{
			return ServiceLocator.Current.GetInstance<TService>();
		}

		public static bool TryGetInstance<TService>(out TService service)
		{
			var registrar = GetInstance<IServiceRegistrar>();
			if (registrar.IsTypeRegistered(typeof(TService)))
			{
				service = ServiceLocator.Current.GetInstance<TService>();
				return true;
			}
			service = default(TService);
			return false;
		}

		public static bool IsTypeRegistered<T>()
		{
			var registrar = GetInstance<IServiceRegistrar>();
			return registrar.IsTypeRegistered(typeof(T));
		}

		public static bool IsTypeRegistered(Type type)
		{
			var registrar = GetInstance<IServiceRegistrar>();
			return registrar.IsTypeRegistered(type);
		}

		/// <summary>
		/// Tries to retrieve the service with the specified instance type.
		/// </summary>
		/// <param name="instanceType">Type of the </param>
		/// <returns>The located instance, or <c>null</c> if not found.</returns>
		public static object TryGetInstance(Type instanceType)
		{
			ArgumentValidator.AssertNotNull(instanceType, "instanceType");

			var registrar = GetInstance<IServiceRegistrar>();
			if (registrar.IsTypeRegistered(instanceType))
			{
				var service = ServiceLocator.Current.GetInstance(instanceType);
				return service;
			}
			return null;
		}

		public static TService GetInstance<TService, TDefaultImplementation>()
			where TDefaultImplementation : TService
		{
			TService service;
			var registrar = GetInstance<IServiceRegistrar>();
			if (registrar.IsTypeRegistered(typeof(TService)))
			{
				service = ServiceLocator.Current.GetInstance<TService>();
			}
			else
			{
				service = ServiceLocator.Current.GetInstance<TDefaultImplementation>();
			}
			return service;
		}

		/// <summary>
		/// Attempts to retrieve the service with the specified type. 
		/// If not found, the specified default type will be used resolved,
		/// and it will be registered.
		/// </summary>
		/// <typeparam name="TService">The type of the service.</typeparam>
		/// <typeparam name="TDefaultImplementation">The type of the default implementation.</typeparam>
		/// <returns></returns>
		public static TService GetSingleton<TService, TDefaultImplementation>()
			where TDefaultImplementation : TService
		{
			TService service;
			var registrar = GetInstance<IServiceRegistrar>();
			if (registrar.IsTypeRegistered(typeof(TService)))
			{
				service = ServiceLocator.Current.GetInstance<TService>();
			}
			else
			{
				service = ServiceLocator.Current.GetInstance<TDefaultImplementation>();
				RegisterInstance<TService>(service);
			}
			return service;
		}

		public static TService GetInstance<TService>(string key)
		{
			return ServiceLocator.Current.GetInstance<TService>(key);
		}

		public static IEnumerable<TService> GetAllInstances<TService>()
		{
			return ServiceLocator.Current.GetAllInstances<TService>();
		}

		public static void RegisterInstance<TService>(TService service)
		{
			var registrar = GetInstance<IServiceRegistrar>();
			registrar.RegisterInstance<TService>(service);
		}

		public static void RegisterType<TFrom, TTo>() where TTo : TFrom
		{
			var registrar = GetInstance<IServiceRegistrar>();
			registrar.RegisterType<TFrom, TTo>();
		}

		public static void RegisterSingleton<TFrom, TTo>() where TTo : TFrom
		{
			var registrar = GetInstance<IServiceRegistrar>();
			registrar.RegisterSingleton<TFrom, TTo>();
		}

		public static void RegisterSingleton(Type fromType, Type toType)
		{
			var registrar = GetInstance<IServiceRegistrar>();
			registrar.RegisterSingleton(fromType, toType);
		}
	}
}
